package com.engine4cloud.tdf.supervision.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.engine4cloud.tdf.common.data.web.query.Pages;
import com.engine4cloud.tdf.common.data.web.query.Queries;
import com.engine4cloud.tdf.common.data.web.response.PageInfo;
import com.engine4cloud.tdf.common.data.web.response.Params;
import com.engine4cloud.tdf.supervision.convert.DcpgInvCrimeNameConvert;
import com.engine4cloud.tdf.supervision.dto.DcpgCrimeNameDTO;
import com.engine4cloud.tdf.supervision.dto.query.DcpgInvCrimeNameQueryDTO;
import com.engine4cloud.tdf.supervision.dto.result.DcpgInvCrimeNameResultDTO;
import com.engine4cloud.tdf.supervision.entity.DcpgInvCrimeNameEntity;
import com.engine4cloud.tdf.supervision.entity.DcpgInvestigationEntity;
import com.engine4cloud.tdf.supervision.mapper.DcpgInvCrimeNameMapper;
import com.engine4cloud.tdf.supervision.service.DcpgInvCrimeNameService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 调查评估被告人罪名信息表
 *
 * @author wenjie
 * @date 2024-02-29 10:50:30
 */
@Service
public class DcpgInvCrimeNameServiceImpl extends ServiceImpl<DcpgInvCrimeNameMapper, DcpgInvCrimeNameEntity> implements DcpgInvCrimeNameService {

    @Override
    public PageInfo<DcpgInvCrimeNameResultDTO> pageList(Params pageable, DcpgInvCrimeNameQueryDTO dto) {
        Page<DcpgInvCrimeNameEntity> page = page(Pages.page(pageable), wrapper(dto));
        return Pages.convert(page, DcpgInvCrimeNameConvert.INSTANCE::convert);
    }

    @Override
    public DcpgInvCrimeNameResultDTO getById(Long id) {
        return DcpgInvCrimeNameConvert.INSTANCE.convert(super.getById(id));
    }

    @Override
    public List<DcpgInvCrimeNameResultDTO> findList(DcpgInvCrimeNameQueryDTO dto) {
        return this.baseMapper.findList(dto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateBatch(DcpgInvestigationEntity investigation, List<DcpgCrimeNameDTO> crimeList) {
        DcpgInvCrimeNameQueryDTO query = new DcpgInvCrimeNameQueryDTO();
        query.setDcpgbh(investigation.getDcpgbh());
        List<DcpgInvCrimeNameResultDTO> existedList = this.findList(query);

        List<DcpgInvCrimeNameEntity> preSavedCrimeNameList = this.preSaveCrimeNameList(investigation, existedList, crimeList);
        if (CollectionUtils.isNotEmpty(preSavedCrimeNameList)) {
            this.saveBatch(preSavedCrimeNameList);
        }

        List<Long> preDeletedCrimeNameList = this.preDeleteCrimeNameIdList(existedList, crimeList);
        if (CollectionUtils.isNotEmpty(preDeletedCrimeNameList)) {
            this.removeBatchByIds(preDeletedCrimeNameList);
        }

        return true;
    }

    private List<DcpgInvCrimeNameEntity> preSaveCrimeNameList(DcpgInvestigationEntity investigation, List<DcpgInvCrimeNameResultDTO> existedList, List<DcpgCrimeNameDTO> crimeNameList) {
        if (CollectionUtils.isEmpty(crimeNameList)) {
            return Collections.emptyList();
        }

        List<DcpgInvCrimeNameEntity> preSaveCrimeNameList = new ArrayList<>();
        Map<String, DcpgInvCrimeNameResultDTO> existedMap = existedList.stream().collect(Collectors.toMap(DcpgInvCrimeNameResultDTO::getZm, Function.identity(), (v1, v2) -> v1));
        crimeNameList.forEach(crime -> {
            if (!existedMap.containsKey(crime.getZm())) {
                preSaveCrimeNameList.add(DcpgInvCrimeNameConvert.INSTANCE.update(investigation, crime.getZm()));
            }
        });

        return preSaveCrimeNameList;
    }


    /**
     * 更新时，需要删除的罪名
     *
     * @param existedList   已经存在的
     * @param crimeNameList 前端传入的罪名对象列表
     * @return List<Long>
     */
    public List<Long> preDeleteCrimeNameIdList(List<DcpgInvCrimeNameResultDTO> existedList, List<DcpgCrimeNameDTO> crimeNameList) {
        if (CollectionUtils.isEmpty(existedList)) {
            return Collections.emptyList();
        }

        Map<String, DcpgCrimeNameDTO> crimeMap = crimeNameList.stream().collect(Collectors.toMap(DcpgCrimeNameDTO::getZm, Function.identity(), (v1, v2) -> v1));
        return existedList.stream().filter(e -> !crimeMap.containsKey(e.getZm())).map(DcpgInvCrimeNameResultDTO::getId).toList();
    }

    private LambdaQueryWrapper<DcpgInvCrimeNameEntity> wrapper(DcpgInvCrimeNameQueryDTO query) {
        LambdaQueryWrapper<DcpgInvCrimeNameEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(DcpgInvCrimeNameEntity::getId, v));
        Queries.accept(query.getDcpgbh(), v -> wrapper.eq(DcpgInvCrimeNameEntity::getDcpgbh, v));
        return wrapper;
    }
}